package com.stxx.stiot2.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.stxx.framwork.constants.StorePolicyType;
import com.stxx.framwork.domain.model.Option;
import com.stxx.framwork.domain.model.PageQuery;
import com.stxx.framwork.domain.model.PageResult;
import com.stxx.framwork.utils.StoreUtils;
import com.stxx.stiot2.constants.SystemConstants;
import com.stxx.stiot2.domain.Profile;
import com.stxx.stiot2.domain.Signal;
import com.stxx.stiot2.domain.ext.SignalEx;
import com.stxx.stiot2.service.ProfileService;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.data.sql.SqlBuilder;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Fuzhenlei
 * @date 2025/01/15 16:41
 */
@Component
public class ProfileServiceImpl implements ProfileService {
    @Inject
    StoreUtils storeUtils;

    private final static Map<String, Map<String, SignalEx>> typeCache = new HashMap<>();
    static List<SignalEx> list = null;

    @Override
    public  Profile queryById(String id)  {
        try {
            return storeUtils.selectById(id, Profile.class);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public int insert(Profile bean) throws SQLException {
        validEntityBeforeSave(bean);
        return storeUtils.insert(bean);
    }

    @Override
    public int update(Profile bean) throws SQLException {
        typeCache.remove(bean.getCode());
        validEntityBeforeSave(bean);
        return storeUtils.update(bean);
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(Profile bean){

    }




    @Override
    public int delete(String name) throws SQLException {
        typeCache.remove(name);
        return storeUtils.delete(Profile.class, name);
    }

    @Override
    public int deleteByIds(String[] ids) throws SQLException {
        for (String id : ids) {
            typeCache.remove(id);
        }
        return storeUtils.deleteByIds(Profile.class, ids);
    }

    @Override
    public List<Profile> list(Profile obj) throws SQLException {
        return storeUtils.selectList(Profile.class,obj);
    }

    @Override
    public PageResult<Profile> pageList(Profile obj, PageQuery pageQuery) throws SQLException {
        return storeUtils.selectPageList(Profile.class,obj,pageQuery);
    }

    @Override
    public List<Option> queryOptions(String id, String w,String pid) throws SQLException {
        SqlBuilder sb = new SqlBuilder();
        sb.append("select code,name,signal_list from "+storeUtils.getTableName(Profile.class));
        if(id != null){
            sb.append(" where code=?",id);
        }else{
            sb.append(" where (code like concat('%',?,'%') or name like concat('%',?,'%'))",w,w);
        }
        sb.append(" limit "+ SystemConstants.options_query_max_size);
        List<Option> options = new ArrayList<>();
        List<Profile> profileList =  storeUtils.sql(sb).queryRowList(Profile.class);
        if(profileList!=null){
            profileList.forEach(item->{
                Option option = new Option();
                option.setLabel(item.getName());
                option.setValue(item.getCode());
                options.add(option);
                if(item.getSignalList()!=null){
                    List<Option> signals = new ArrayList<>();
                    item.getSignalList().forEach(signal -> {
                        Option signalOption = new Option();
                        signalOption.setLabel(signal.getName());
                        signalOption.setValue(signal.getCode());
                        signals.add(signalOption);
                    });
                    option.setExt(signals);
                }
            });

        }
        return options;
    }

    @Override
    public List<Option> queryOptions(String[] ids) throws SQLException {
        SqlBuilder sb = new SqlBuilder();
        sb.append("select code as value,name as label from "+storeUtils.getTableName(Profile.class)+" where code in (");
        sb.append(StrUtil.repeat("?,",ids.length));
        sb.removeLast();
        sb.append(")",ids);
        return storeUtils.sql(sb).queryRowList(Option.class);
    }

    @Override
    public Map<String, SignalEx> signals(String profileCode) {
        Map<String,SignalEx> fluxDataTypeMap;
        List<SignalEx> periodSignals;
        if(typeCache.containsKey(profileCode)){
            fluxDataTypeMap = typeCache.get(profileCode);
        }else{
            fluxDataTypeMap = new HashMap<>();
            Profile profile;
            try {
                profile = storeUtils.selectById(profileCode,Profile.class);
                profile.getSignalList().forEach(item->{
                    SignalEx ex= BeanUtil.toBean(item,SignalEx.class);
                    ex.setProfileCode(profile.getCode());
                    fluxDataTypeMap.put(item.getCode(),ex );
                });
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
            typeCache.put(profileCode, fluxDataTypeMap);
            list = null;
        }
        return fluxDataTypeMap;
    }


    @Override
    public List<SignalEx> periodSignals() {
        if(list==null){
            list = typeCache.values().stream()
                    .flatMap(innerMap -> innerMap.values().stream())
                    .filter(item->item.getStorePolicy()== StorePolicyType.PERIOD||item.getStorePolicy()== StorePolicyType.PER_CH)
                    .collect(Collectors.toList());
        }
        return list;
    }
}
